<template>
  <div class="widget-form-container">
		<div v-if="!widgetForm.list || widgetForm.list.length === 0" class="form-empty">
			从左侧拖拽来添加标签
		</div>
    <el-form
      label-suffix=":"
      :size="widgetForm.config.size"
      :label-position="widgetForm.config.labelPosition"
      :label-width="`${widgetForm.config.labelWidth}px`"
      :hide-required-asterisk="widgetForm.config.hideRequiredAsterisk"
    >
      <Draggable
        class="widget-form-list"
        item-key="key"
        ghostClass="ghost"
        :animation="200"
        :group="{ name: 'people' }"
        :list="widgetForm.list"
        @add="handleMoveAdd"
      >
				<transition-group name="fade" tag="div" v-for="(element, index) of widgetForm.list" :key='index'>
					<template v-if="element.type === 'grid'">
						<el-row
							class="widget-col widget-view"
							type="flex"
							v-if="element.key"
							:key="element.key"
							:class="{ active: widgetFormSelect?.key === element.key }"
							:gutter="element.options.gutter ?? 0"
							:justify="element.options.justify"
							:align="element.options.align"
							@click="handleItemClick(element)"
						>
							<el-col
								v-for="(col, colIndex) of element.columns"
								:key="colIndex"
								:span="col.span ?? 0"
							>
								<Draggable
									class="widget-col-list"
									item-key="key"
									ghostClass="ghost"
									:animation="200"
									:group="{ name: 'people' }"
									:no-transition-on-drag="true"
									:list="col.list"
									@add="handleColMoveAdd($event, element, colIndex)"
								>
									<transition-group name="fade" tag="div" v-for="(element, index) of col.list" :key='index'>
										<ElWidgetFormItem
											v-if="element.key"
											:key="element.key"
											:element="element"
											:config="widgetForm.config"
											:selectWidget="widgetFormSelect"
											@click.stop="handleItemClick(element)"
											@copy="handleCopyClick(index, col.list)"
											@delete="handleDeleteClick(index, col.list)"
										/>
									</transition-group>
								</Draggable>
							</el-col>
							<div
								class="widget-view-action widget-col-action"
								v-if="widgetFormSelect?.key === element.key"
							>
								<SvgIcon
									name="fdelete"
									@click.stop="handleDeleteClick(index, widgetForm.list)"
								/>
							</div>

							<div
								class="widget-view-drag widget-col-drag"
								v-if="widgetFormSelect?.key === element.key"
							>
								<SvgIcon name="fmove" />
							</div>
						</el-row>
					</template>
					<template v-else-if='element.type === "table"'>
						<div
							class="widget-col widget-view-table widget-view"
							:class="{ active: widgetFormSelect?.key === element.key }"
							@click="handleItemClick(element)"
						>
							<table style='width: 100%'>
								<tr>
									<td>
										<Draggable
											class="widget-col-list"
											item-key="key"
											ghostClass="ghost"
											:animation="200"
											:group="{ name: 'people' }"
											:no-transition-on-drag="true"
											:list="[]"
											@add="handleColMoveAdd($event, element, colIndex)"
										>
											<transition-group name="fade" tag="div" v-for="(element, index) of []" :key='index'>
												<ElWidgetFormItem
													v-if="element.key"
													:key="element.key"
													:element="element"
													:config="widgetForm.config"
													:selectWidget="widgetFormSelect"
													@click.stop="handleItemClick(element)"
													@copy="handleCopyClick(index, col.list)"
													@delete="handleDeleteClick(index, col.list)"
												/>
											</transition-group>
										</Draggable>
									</td>
								</tr>
							</table>
							<div class="widget-view-action widget-col-action" v-if="widgetFormSelect?.key === element.key">
								<SvgIcon name="fdelete" @click.stop="handleDeleteClick(index, widgetForm.list)" />
							</div>
							<div class="widget-view-drag widget-col-drag" v-if="widgetFormSelect?.key === element.key">
								<SvgIcon name="fmove" />
							</div>
						</div>
					</template>
					<template v-else>
						<ElWidgetFormItem
							v-if="element.key"
							:key="element.key"
							:element="element"
							:config="widgetForm.config"
							:selectWidget="widgetFormSelect"
							@click="handleItemClick(element)"
							@copy="handleCopyClick(index, widgetForm.list)"
							@delete="handleDeleteClick(index, widgetForm.list)"
						/>
					</template>
				</transition-group>
      </Draggable>
    </el-form>
  </div>
</template>

<script lang="ts">
import { defineComponent, nextTick, PropType } from 'vue';
import { VueDraggableNext } from 'vue-draggable-next'
import { v4 } from 'uuid'
import ElWidgetFormItem from './ElWidgetFormItem.vue'
import SvgIcon from '/@/components/svgIcon/index.vue';
import { WidgetForm } from '/@/components/formGenerator/config/element'

const handleListInsert = (key: string, list: any[], obj: any) => {
  const newList: any[] = []
  list.forEach(item => {
    if (item.key === key) {
      newList.push(item)
      newList.push(obj)
    } else {
      if (item.columns) {
        item.columns = item.columns.map((col: any) => ({
          ...col,
          list: handleListInsert(key, col.list, obj)
        }))
      }
      newList.push(item)
    }
  })
  return newList
}

const handleListDelete = (key: string, list: any[]) => {
  const newList: any[] = []
  list.forEach(item => {
    if (item.key !== key) {
      if (item.columns) {
        item.columns = item.columns.map((col: any) => ({
          ...col,
          list: handleListDelete(key, col.list)
        }))
      }
      newList.push(item)
    }
  })
  return newList
}

export default defineComponent({
  name: 'ElWidgetForm',
  components: {
    SvgIcon,
    Draggable: VueDraggableNext,
    ElWidgetFormItem
  },
  props: {
    widgetForm: {
      type: Object as PropType<WidgetForm>,
      required: true
    },
    widgetFormSelect: {
      type: Object
    }
  },
  emits: ['update:widgetForm', 'update:widgetFormSelect'],
  setup(props, context) {
    const handleItemClick = (row: any) => {
      context.emit('update:widgetFormSelect', row)
    }

    const handleCopyClick = (index: number, list: any[]) => {
      const key = v4().replaceAll('-', '').substr(0,20)
      const oldList = JSON.parse(JSON.stringify(props.widgetForm.list))

      let copyData = {
        ...list[index],
        key,
        model: `${list[index].type}_${key}`,
        rules: list[index].rules ?? []
      }

      if (
        list[index].type === 'radio' ||
        list[index].type === 'checkbox' ||
        list[index].type === 'select'
      ) {
        copyData = {
          ...copyData,
          options: {
            ...copyData.options,
            options: copyData.options.options.map((item: any) => ({ ...item }))
          }
        }
      }

      context.emit('update:widgetForm', {
        ...props.widgetForm,
        list: handleListInsert(list[index].key, oldList, copyData)
      })

      context.emit('update:widgetFormSelect', copyData)
    }

    const handleDeleteClick = (index: number, list: any[]) => {
      const oldList = JSON.parse(JSON.stringify(props.widgetForm.list))

      if (list.length - 1 === index) {
        if (index === 0) {
          nextTick(() => context.emit('update:widgetFormSelect', null))
        } else {
          context.emit('update:widgetFormSelect', list[index - 1])
        }
      } else {
        context.emit('update:widgetFormSelect', list[index + 1])
      }

      context.emit('update:widgetForm', {
        ...props.widgetForm,
        list: handleListDelete(list[index].key, oldList)
      })
    }

    const handleMoveAdd = (event: any) => {
      const { newIndex } = event

      const key = v4().replaceAll('-', '').substr(0,20)
      const list = JSON.parse(JSON.stringify(props.widgetForm.list))

      list[newIndex] = {
        ...list[newIndex],
        key,
        model: `${list[newIndex].type}_${key}`,
        rules: []
      }

      if (
        list[newIndex].type === 'radio' ||
        list[newIndex].type === 'checkbox' ||
        list[newIndex].type === 'select'
      ) {
        list[newIndex] = {
          ...list[newIndex],
          options: {
            ...list[newIndex].options,
            options: list[newIndex].options.options.map((item: any) => ({
              ...item
            }))
          }
        }
      }

      if (list[newIndex].type === 'grid') {
        list[newIndex] = {
          ...list[newIndex],
          columns: list[newIndex].columns.map((item: any) => ({ ...item }))
        }
      }
      context.emit('update:widgetForm', { ...props.widgetForm, list })

      context.emit('update:widgetFormSelect', list[newIndex])
    }

    const handleColMoveAdd = (
      event: any,
      row: any,
      index: string | number | symbol
    ) => {
      const { newIndex, oldIndex, item } = event
      const list = JSON.parse(JSON.stringify(props.widgetForm.list))

      if (item.className.includes('data-grid')) {
        item.tagName === 'DIV' &&
          list.splice(oldIndex, 0, row.columns[index].list[newIndex])
        row.columns[index].list.splice(newIndex, 1)
        return false
      }

      const key = v4().replaceAll('-', '').substr(0,20)

      row.columns[index].list[newIndex] = {
        ...row.columns[index].list[newIndex],
        key,
        model: `${row.columns[index].list[newIndex].type}_${key}`,
        rules: []
      }

      if (
        row.columns[index].list[newIndex].type === 'radio' ||
        row.columns[index].list[newIndex].type === 'checkbox' ||
        row.columns[index].list[newIndex].type === 'select'
      ) {
        row.columns[index].list[newIndex] = {
          ...row.columns[index].list[newIndex],
          options: {
            ...row.columns[index].list[newIndex].options,
            options: row.columns[index].list[
              newIndex
            ].options.options.map((item: any) => ({ ...item }))
          }
        }
      }

      context.emit('update:widgetFormSelect', row.columns[index].list[newIndex])
    }

    return {
      handleItemClick,
      handleCopyClick,
      handleDeleteClick,
      handleMoveAdd,
      handleColMoveAdd
    }
  }
})
</script>

<style lang='scss' scoped>
.widget-view-table {
	table, th, td {
		border: 1px solid #999999;
		border-collapse: collapse;
	}
	table {
		width: 100%;
	}

	td {
		padding: 3px;
	}
}
</style>
